﻿using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace WinFormsApp1
{
    public partial class DoodleForm : Form
    {
        [DllImport("user32.dll")]
        static extern IntPtr GetDC(IntPtr hwnd);

        [DllImport("user32.dll")]
        static extern int ReleaseDC(IntPtr hwnd, IntPtr hdc);

        [DllImport("gdi32.dll")]
        static extern bool MoveToEx(IntPtr hdc, int X, int Y, IntPtr lpPoint);

        [DllImport("gdi32.dll")]
        static extern bool LineTo(IntPtr hdc, int X, int Y);

        [DllImport("gdi32.dll")]
        static extern IntPtr CreatePen(int fnPenStyle, int nWidth, uint crColor);

        [DllImport("gdi32.dll")]
        static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);

        [DllImport("gdi32.dll")]
        static extern bool DeleteObject(IntPtr hObject);

        private const int PS_SOLID = 0;
        private IntPtr desktopDC;
        private Point previousPoint;
        private bool isDrawing = false;
        private Color currentColor = Color.Red;
        private int penWidth = 3;

        public DoodleForm()
        {
            InitializeForm();
            desktopDC = GetDC(IntPtr.Zero);
        }

        private void InitializeForm()
        {
            this.Text = "桌面涂鸦板";
            this.FormBorderStyle = FormBorderStyle.FixedToolWindow;
            this.StartPosition = FormStartPosition.Manual;
            this.Location = new Point(100, 100);
            this.Size = new Size(200, 100);
            this.TopMost = true;
            this.BackColor = Color.LightGray;

            Button colorBtn = new Button { Text = "颜色", Location = new Point(10, 10), Size = new Size(80, 30) };
            Button clearBtn = new Button { Text = "清空", Location = new Point(100, 10), Size = new Size(80, 30) };
            Button exitBtn = new Button { Text = "退出", Location = new Point(10, 50), Size = new Size(170, 30) };

            colorBtn.Click += ColorBtn_Click;
            clearBtn.Click += ClearBtn_Click;
            exitBtn.Click += ExitBtn_Click;

            this.Controls.Add(colorBtn);
            this.Controls.Add(clearBtn);
            this.Controls.Add(exitBtn);

            this.MouseDown += DoodleForm_MouseDown;
            this.MouseUp += DoodleForm_MouseUp;
            this.FormClosed += DoodleForm_FormClosed;
        }

        private void StartDrawing(Point startPoint)
        {
            isDrawing = true;
            previousPoint = startPoint;
        }

        private void DrawLine(Point endPoint)
        {
            if (!isDrawing) return;

            uint color = (uint)(currentColor.B << 16 | currentColor.G << 8 | currentColor.R);
            IntPtr pen = CreatePen(PS_SOLID, penWidth, color);
            IntPtr oldPen = SelectObject(desktopDC, pen);

            MoveToEx(desktopDC, previousPoint.X, previousPoint.Y, IntPtr.Zero);
            LineTo(desktopDC, endPoint.X, endPoint.Y);

            SelectObject(desktopDC, oldPen);
            DeleteObject(pen);

            previousPoint = endPoint;
        }

        private void StopDrawing() => isDrawing = false;

        private void DoodleForm_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
                StartDrawing(this.PointToScreen(e.Location));
        }

        private void DoodleForm_MouseUp(object sender, MouseEventArgs e) => StopDrawing();

        protected override void WndProc(ref Message m)
        {
            const int WM_MOUSEMOVE = 0x0200;

            if (m.Msg == WM_MOUSEMOVE && isDrawing)
            {
                Point screenPoint = this.PointToScreen(new Point(m.LParam.ToInt32() & 0xFFFF, m.LParam.ToInt32() >> 16));
                DrawLine(screenPoint);
            }

            base.WndProc(ref m);
        }

        private void ColorBtn_Click(object sender, EventArgs e)
        {
            ColorDialog dialog = new ColorDialog();
            if (dialog.ShowDialog() == DialogResult.OK)
                currentColor = dialog.Color;
        }

        private void ClearBtn_Click(object sender, EventArgs e)
        {
            // 清空桌面需要刷新Explorer
            IntPtr result = FindWindow("Progman", "Program Manager");
            SendMessageTimeout(result, 0x001A, IntPtr.Zero, IntPtr.Zero, 0, 1000, out _);
        }

        private void ExitBtn_Click(object sender, EventArgs e) => Application.Exit();

        private void DoodleForm_FormClosed(object sender, FormClosedEventArgs e) => ReleaseDC(IntPtr.Zero, desktopDC);

        [DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

        [DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr SendMessageTimeout(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam, uint fuFlags, uint uTimeout, out IntPtr lpdwResult);

        //[STAThread]
        //static void Main()
        //{
        //    Application.EnableVisualStyles();
        //    Application.SetCompatibleTextRenderingDefault(false);
        //    Application.Run(new DoodleForm());
        //}
    }
}